package com.stockz.equity.model;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Transient;



@IdClass(BarPrimaryKey.class)
@Entity
@NamedQueries({
	@NamedQuery(name=Bar.GetBarListByScripCodeQuery, query="select b from Bar b where b.scripCode = ?  order by b.date desc"),
	@NamedQuery(name=Bar.GetBarListByDateQuery, query="select b from Bar b where b.date = ?")
	})
@Table(name="BAR")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Bar implements Serializable, Comparable<Bar>, Cloneable {
	private static final long serialVersionUID = 8675970911933455776L;
	
	public static final String GetBarListByScripCodeQuery = "getBarListByScripCodeQuery";
	public static final String GetBarListByDateQuery = "getBarListByScripCodeAfterDateQuery";
	
	public enum BarValueType{
		OPEN,
		HIGH,
		LOW,
		CLOSE,
		LAST,
		PREVCLOSE,
		VOLUME,
		MID,
		TURNOVER,
		TRADES,
		AVGPRICE,
		AVGTRADEPRICE,
		AVGTRADESIZE,
		SPREAD,
		CRUNCH,
		ACTIVITY;
	}
	
	@Id
	@Column(name="CODE")
	@org.hibernate.annotations.Index(name = "barIndex_scripCode")
	private String scripCode;
	
	@Transient
	private Scrip scrip;
	
	
	@Id
	@Column(name="BARDATE")
	private Date date;
	@Column(name="OPEN")
	private double open;
	@Column(name="HIGH")
	private double high;
	@Column(name="LOW")
	private double low;
	@Column(name="CLOSE")
	private double close;
	@Column(name="LAST")
	private double last;
	@Column(name="VOLUME")
	private double volume;
	@Column(name="TRADES")
	private double trades;
	@Column(name="TURNOVER")
	private double turnover;
	@Column(name="PREVCLOSE")
	private double previousClose;
	
	@Override
	public int compareTo(Bar bar) {
		if(null != bar && null != bar.getDate() && null != getDate()){
			if(bar.getDate().after(getDate())){
				return 1;
			}else if(bar.getDate().before(getDate())){
				return -1;
			}else{
				return 0;
			}
		}
		return 0;
	}

	@Override
	protected Bar clone() {
		Bar bar = new Bar();
		bar.setScripCode(getScripCode());
		bar.setDate(getDate());
		bar.setOpen(getOpen());
		bar.setHigh(getHigh());
		bar.setLow(getLow());
		bar.setClose(getClose());
		bar.setLast(getLast());
		bar.setVolume(getVolume());
		bar.setTurnover(getTurnover());
		bar.setTrades(getTrades());
		return bar;
	};
	
	public double getValue(BarValueType valueType){
		switch(valueType){
		case OPEN : return getOpen();
		case HIGH : return getHigh();
		case LOW : return getLow();
		case CLOSE : return getClose();
		case LAST : return getLast();
		case PREVCLOSE : return getPreviousClose();
		case VOLUME : return getVolume();
		case TRADES : return getTrades();
		case TURNOVER : return getTurnover();
		case AVGPRICE : return getAveragePrice();
		case AVGTRADEPRICE : return getAverageTradePrice();
		case AVGTRADESIZE : return getAverageTradeSize();
		case SPREAD : return getSpread();
		case CRUNCH : return getCrunch();
		case ACTIVITY : return getActivity();
		case MID : return getMid();
		default : return getAveragePrice();
		}
	}
	
	public double getMid(){
		return (getHigh()+getLow())/2;
	}
	
	public double getActivity(){
		return getVolume()*getSpread()/getLow();
	}

	public double getCrunch(){
		return getVolume()/getSpread();
	}
	
	public double getSpread(){
		if(getHigh()==getLow()){
			return 0.01;
		}else{
			return getHigh()-getLow();			
		}
	}
	
	public double getAveragePrice(){
		if(getVolume() <= 0){
			return 0;
		}
		return getTurnover()/getVolume();
	}
	
	public double getAverageTradeSize(){
		if(getTrades() <= 0){
			return 0;
		}
		return getVolume()/getTrades();
	}

	public double getAverageTradePrice(){
		if(getTrades() <= 0){
			return 0;
		}
		return getTurnover()/getTrades();
	}
	
	public double getOpen() {
		return open;
	}


	public void setOpen(double open) {
		this.open = open;
	}


	public double getHigh() {
		return high;
	}


	public void setHigh(double high) {
		this.high = high;
	}


	public double getLow() {
		return low;
	}


	public void setLow(double low) {
		this.low = low;
	}


	public double getClose() {
		return close;
	}


	public void setClose(double close) {
		this.close = close;
	}


	public double getLast() {
		return last;
	}


	public void setLast(double last) {
		this.last = last;
	}


	public double getVolume() {
		return volume;
	}


	public void setVolume(double volume) {
		this.volume = volume;
	}


	public double getTrades() {
		return trades;
	}


	public void setTrades(double trades) {
		this.trades = trades;
	}


	public double getTurnover() {
		return turnover;
	}


	public void setTurnover(double turnover) {
		this.turnover = turnover;
	}


	public Date getDate() {
		return date;
	}


	public void setDate(Date date) {
		this.date = date;
	}

	public double getPreviousClose() {
		return previousClose;
	}

	public void setPreviousClose(double previousClose) {
		this.previousClose = previousClose;
	}

	public Scrip getScrip() {
		return scrip;
	}

	public void setScrip(Scrip scrip) {
		this.scrip = scrip;
	}

	public String getScripCode() {
		return scripCode;
	}

	public void setScripCode(String scripCode) {
		this.scripCode = scripCode;
	}

}
